#ifndef COLA_H_
#define COLA_H_

#include <typeinfo>

#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <errno.h>

#include <iostream>

#define MSG_OK			0
#define	ERROR_FTOK_MSG	-1
#define ERROR_MSGGET	-2

template <class T> class Cola {
	private:
		key_t	clave;

	public:
		int		id;

		Cola ();
		~Cola();
		void removerID ();
		int crear ( char *archivo,char letra );
		int escribir ( T dato );
		int leer ( int tipo,T* buffer );

		void mostrarResultado (int resultado);
};

template <class T> Cola<T> :: Cola ( ) {

}

template <class T> Cola<T> :: ~Cola () {

}

template <class T> void Cola<T> :: removerID () {
	msgctl ( this->id,IPC_RMID,NULL );
}

template <class T> int Cola<T> :: crear ( char *archivo,char letra ) {

	FILE *fd = fopen (archivo, "w+");
	fclose(fd);

	this->clave = ftok ( archivo,letra );

	if ( this->clave == -1 ) {
		return ERROR_FTOK_MSG;
	}

	this->id = msgget ( this->clave,0666|IPC_CREAT );
	if ( this->id == -1 ) {
		return ERROR_MSGGET;
	}

	return MSG_OK;
}

template <class T> void Cola<T> :: mostrarResultado (int resultado) {
	std::cout << "Resultado: "<<resultado<< " ";
	if (resultado == -1) {
		switch errno {
			case EACCES:
				std::cout << "Error: EACCES";
				break;
			case EAGAIN:
				std::cout << "Error: EAGAIN";
				break;
			case EFAULT:
				std::cout << "Error: EFAULT";
				break;
			case EIDRM:
				std::cout << "Error: EIDRM";
				break;
			case EINTR:
				std::cout << "Error: EINTR";
				break;
			case EINVAL:
				std::cout << "Error: EINVAL";
				break;
			case ENOMEM:
				std::cout << "Error: ENOMEM";
				break;
			default:
				std::cout << "Error: errno desconocido";
				break;
		}
	}
	std::cout << std::endl;
}

template <class T> int Cola<T> :: escribir ( T dato ) {
	int resultado = msgsnd ( this->id,(const void *)&dato,sizeof(T)-sizeof(long),0 );
	return resultado;
}

template <class T> int Cola<T> :: leer ( int tipo,T* buffer ) {
	int resultado = msgrcv ( this->id,(void *)buffer,sizeof(T)-sizeof(long),tipo,0 );
	return resultado;
}

#endif /* COLA_H_ */
